package com.example.myapplication;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.textfield.TextInputEditText;

import org.apache.log4j.BasicConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;

import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import client.Client;
import signal.JSonRPCImpl;
import signal.Role;
import signal.Signal;
import signal.Transport;
import stream.LocalStream;
import utils.WebRTCEglUtils;
import utils.WebRTCUtils;
import webrtcwrappers.WebRTCCapturer;

public class MainActivity extends AppCompatActivity {
    public static final String[] WEBRTC_PERMISSIONS = new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.RECORD_AUDIO};
    public static final int WEBRTC_PERMISSIONS_REQUEST_CODE = 12345;
    private static final Logger logger = LoggerFactory.getLogger(MainActivity.class);
    private ExecutorService executorService;

    private PeerConnectionFactory peerConnectionFactory;
    private VideoSource localVideoSource;
    private VideoTrack localVideoTrack;

    private SurfaceViewRenderer localVideoView;
    private SurfaceViewRenderer remoteVideoView;
    private Button start;
    private Button join;
    private Button endCall;
    private VideoCapturer localVideoCapturer;
    private LocalStream localStream;
    private Signal signal;
    private Client client;

    /**
     * step:
     * 1. get local stream, store this to local peer
     * 2. create offer with this stream
     * 3. send offer to the moon
     */
    @SuppressLint("NonConstantResourceId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        BasicConfigurator.configure();
        super.onCreate(savedInstanceState);
        initComponents();
        initHandlers();

    }


    void initComponents() {
        WebRTCUtils.requestPermissions(this, WEBRTC_PERMISSIONS, WEBRTC_PERMISSIONS_REQUEST_CODE);
        setContentView(R.layout.activity_main);
        start = findViewById(R.id.start_call);
        join = findViewById(R.id.join);
        endCall = findViewById(R.id.endcall);
        localVideoView = findViewById(R.id.localView);
        localVideoView.setMirror(true);
        localVideoView.setEnableHardwareScaler(true);

        remoteVideoView = findViewById(R.id.remoteView);
        remoteVideoView.setMirror(false);
        initHandlers();
    }


    void initHandlers() {
        executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        start.setOnClickListener((View v) -> start());
        endCall.setOnClickListener((View v) -> hangup());
        join.setOnClickListener((View v) -> executorService.submit(this::joinSession));
    }

    private void joinSession() {
        String url = ((TextInputEditText) findViewById(R.id.url)).getText().toString();
        if (url != null && !url.isEmpty()) {
            signal = new JSonRPCImpl(url);
        } else {
            signal = new JSonRPCImpl("ws://10.0.2.2:7000/ws");
        }
        client = new Client(signal, null, this);
        client.join("test session", UUID.randomUUID().toString());
    }


    public void start() {
        peerConnectionFactory = Client.getPeerConnectionFactory(this);
        localStream = new LocalStream().getUserMedia(peerConnectionFactory);
        runOnUiThread(this::startLocalVideoCapturing);
        Transport publisher = client.getTransports().get(Role.PUBLISHER);
        assert publisher != null;
        client.publish(localStream);
    }


    private void startLocalVideoCapturing() {
        localVideoCapturer = WebRTCCapturer.createCapturer(this);
        if (localVideoCapturer != null) {
            SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", WebRTCEglUtils.getRootEglBaseContext());
            localVideoSource = localStream.getVideoSource();
            localVideoCapturer.initialize(surfaceTextureHelper, this, localVideoSource.getCapturerObserver());
            localVideoCapturer.startCapture(1024, 768, 30);
        }
        localVideoTrack = localStream.getVideoTrack();
        localVideoTrack.addSink(localVideoView);
    }

    private void stopVideoCapturing() {
        localVideoSource = null;
        localVideoTrack = null;
        localVideoCapturer = null;
    }


    private void hangup() {
        stopVideoCapturing();
        client.close();
    }

    public SurfaceViewRenderer getRemoteVideoView() {
        return remoteVideoView;
    }

}
